#include "widget.h"
#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QPushButton>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMessageBox>
#include <QUrl>
#include <QDebug>
#include <QRadioButton>   // 包含 QRadioButton
#include <QStackedWidget> // 包含 QStackedWidget
#include <QGroupBox>      // 包含 QGroupBox
#include <QRandomGenerator>

// using namespace std::placeholders; // 如果用了 std::bind 才需要

Widget::Widget(QWidget *parent)
    : QWidget(parent),
    janusClient_(new JanusClient(this)), // <<<=== 创建 JanusClient 实例
    camera_(new CCamera(this)),
    meetingUI_(nullptr),
    isRegistered_(false)
{
    setupUi();           // 创建 UI 元素和布局
    setWindowTitle("Janus Client"); // 设置窗口标题
    setMinimumWidth(400);  // 调整最小宽度

    // --- 连接 JanusClient 信号 ---
    connect(janusClient_, &JanusClient::stateChanged, this, &Widget::onJanusStateChanged);
    connect(janusClient_, &JanusClient::sessionCreated, this, &Widget::onJanusSessionCreated);
    connect(janusClient_, &JanusClient::errorOccurred, this, &Widget::onJanusErrorOccurred);
    // 子类特定的信号 (janusEventReceived, jsepReceived 等) 在这里不连接，
    // 应该在实际的 VideoRoomClient/VideoCallClient 与 VideoMeetingUI 或其他处理逻辑之间连接

    // --- 连接 UI 控件信号 ---
    // 模式切换
    connect(videoRoomRadioButton_, &QRadioButton::toggled, this, &Widget::onModeChanged);
    // connect(videoCallRadioButton_, &QRadioButton::toggled, this, &Widget::onModeChanged); // 连一个就行

    // 按钮 (VideoRoom 和 VideoCall 的启动按钮都连接到 on_startSession_clicked)
    connect(joinRoomButton_, &QPushButton::clicked, this, &Widget::on_startSession_clicked);
    connect(callButton_, &QPushButton::clicked, this, &Widget::on_startSession_clicked);
    connect(registerButton_, &QPushButton::clicked, this, &Widget::on_registerButton_clicked);
    connect(exitButton_, &QPushButton::clicked, this, &Widget::on_exitButton_clicked);

    // CCamera
    connect(camera_, &CCamera::cameraListUpdated, this, &Widget::updateCameraComboBox);
    connect(camera_, &CCamera::errorOccurred, this, &Widget::onCameraError);
    connect(cameraComboBox_, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Widget::onCameraSelected);

    // --- 初始化 ---
    updateCameraComboBox(camera_->getAvailableCamerasDescriptions()); // 初始填充摄像头
    onModeChanged(); // 根据默认选中的模式设置初始 UI 状态

    // 设置默认的 Janus URL (可选)
    janusUrlLineEdit_->setText("ws://127.0.0.1:8188"); // 改为你实际的地址
}

Widget::~Widget()
{
    qDebug() << "Widget destructor called.";
    // janusClient_ 和 camera_ 会自动删除
    // meetingUI_ 应该在 onMeetingUiClosed 中被 deleteLater
}

// --- UI 创建 ---

void Widget::setupUi()
{
    mainLayout_ = new QVBoxLayout(this); // 主垂直布局

    // 1. 模式选择区域
    modeSelectionGroup_ = new QGroupBox("选择模式", this);
    QHBoxLayout* modeLayout = new QHBoxLayout(modeSelectionGroup_);
    videoRoomRadioButton_ = new QRadioButton("视频会议 (VideoRoom)", modeSelectionGroup_);
    videoCallRadioButton_ = new QRadioButton("P2P 呼叫 (VideoCall)", modeSelectionGroup_);
    modeLayout->addWidget(videoRoomRadioButton_);
    modeLayout->addWidget(videoCallRadioButton_);
    videoRoomRadioButton_->setChecked(true); // 默认选中 VideoRoom
    mainLayout_->addWidget(modeSelectionGroup_);

    // 2. 通用输入区域 (Janus URL)
    QHBoxLayout* urlLayout = new QHBoxLayout();
    janusUrlLabel_ = new QLabel("Janus 地址:", this);
    janusUrlLineEdit_ = new QLineEdit(this);
    janusUrlLineEdit_->setPlaceholderText("例如: ws://127.0.0.1:8188");
    urlLayout->addWidget(janusUrlLabel_);
    urlLayout->addWidget(janusUrlLineEdit_);
    mainLayout_->addLayout(urlLayout);


    // 3. 堆叠窗口，用于切换不同模式的 UI
    stackedWidget_ = new QStackedWidget(this);

    // 3.1 创建 VideoRoom UI 面板
    videoRoomWidget_ = new QWidget(stackedWidget_);
    setupVideoRoomUi(videoRoomWidget_);
    stackedWidget_->addWidget(videoRoomWidget_);

    // 3.2 创建 VideoCall UI 面板
    videoCallWidget_ = new QWidget(stackedWidget_);
    setupVideoCallUi(videoCallWidget_);
    stackedWidget_->addWidget(videoCallWidget_);

    mainLayout_->addWidget(stackedWidget_); // 将堆叠窗口添加到主布局

    // 4. 通用摄像头选择
    QHBoxLayout* cameraLayout = new QHBoxLayout();
    cameraLabel_ = new QLabel("摄像头:", this);
    cameraComboBox_ = new QComboBox(this);
    cameraLayout->addWidget(cameraLabel_);
    cameraLayout->addWidget(cameraComboBox_);
    mainLayout_->addLayout(cameraLayout);

    // 5. 底部退出按钮
    QHBoxLayout* bottomButtonLayout = new QHBoxLayout();
    exitButton_ = new QPushButton("退出程序", this);
    bottomButtonLayout->addStretch(1);
    bottomButtonLayout->addWidget(exitButton_);
    bottomButtonLayout->addStretch(1);
    mainLayout_->addLayout(bottomButtonLayout);

    // 设置边距和间距
    mainLayout_->setContentsMargins(10, 10, 10, 10);
    mainLayout_->setSpacing(10);
}

void Widget::setupVideoRoomUi(QWidget* parent)
{
    QVBoxLayout* layout = new QVBoxLayout(parent);
    layout->setContentsMargins(0, 5, 0, 5);
    layout->setSpacing(10);

    QFormLayout* formLayout = new QFormLayout();
    roomIdLabel_ = new QLabel("房间号:", parent);
    roomIdLineEdit_ = new QLineEdit(parent);
    roomIdLineEdit_->setPlaceholderText("输入要加入的房间号");
    formLayout->addRow(roomIdLabel_, roomIdLineEdit_);
    layout->addLayout(formLayout);

    QHBoxLayout* buttonLayout = new QHBoxLayout();
    joinRoomButton_ = new QPushButton("加入房间", parent);
    buttonLayout->addStretch(1);
    buttonLayout->addWidget(joinRoomButton_);
    buttonLayout->addStretch(1);
    layout->addLayout(buttonLayout);
}

void Widget::setupVideoCallUi(QWidget* parent)
{
    QVBoxLayout* layout = new QVBoxLayout(parent);
    layout->setContentsMargins(0, 5, 0, 5);
    layout->setSpacing(10);

    QFormLayout* formLayout = new QFormLayout();

    userNameLabel_ = new QLabel("你的用户名:", parent);
    userNameLineEdit_ = new QLineEdit(parent);
    userNameLineEdit_->setPlaceholderText("在此输入你的用户名");

    QHBoxLayout* registerLayout = new QHBoxLayout(); // 用户名和注册按钮在一行
    registerLayout->addWidget(userNameLineEdit_);
    registerButton_ = new QPushButton("注册", parent);
    registerLayout->addWidget(registerButton_);

    formLayout->addRow(userNameLabel_, registerLayout); // 将包含按钮的布局添加到表单

    peerUserNameLabel_ = new QLabel("对方用户名:", parent);
    peerUserNameLineEdit_ = new QLineEdit(parent);
    peerUserNameLineEdit_->setPlaceholderText("输入要呼叫的用户名");
    formLayout->addRow(peerUserNameLabel_, peerUserNameLineEdit_);

    layout->addLayout(formLayout);

    QHBoxLayout* buttonLayout = new QHBoxLayout();
    callButton_ = new QPushButton("发起呼叫", parent);
    callButton_->setEnabled(false); // 初始禁用，注册后启用
    buttonLayout->addStretch(1);
    buttonLayout->addWidget(callButton_);
    buttonLayout->addStretch(1);
    layout->addLayout(buttonLayout);
}


// --- 槽函数实现 ---

void Widget::onModeChanged()
{
    if (videoRoomRadioButton_->isChecked()) {
        currentMode_ = UIMode::VideoRoom;
        stackedWidget_->setCurrentWidget(videoRoomWidget_);
        setWindowTitle("Janus Client - Video Room");
    } else {
        currentMode_ = UIMode::VideoCall;
        stackedWidget_->setCurrentWidget(videoCallWidget_);
        setWindowTitle("Janus Client - Video Call");
        callButton_->setEnabled(isRegistered_); // 根据注册状态设置呼叫按钮
        registerButton_->setEnabled(!isRegistered_); // 如果已注册，禁用注册按钮
    }
    // 可以在这里重置输入字段或按钮状态
    // roomIdLineEdit_->clear();
    // userNameLineEdit_->clear();
    // peerUserNameLineEdit_->clear();
    // ...
}

void Widget::on_registerButton_clicked()
{
    if (currentMode_ != UIMode::VideoCall) return;

    QString userName = userNameLineEdit_->text().trimmed();
    if (userName.isEmpty()) {
        QMessageBox::warning(this, "输入错误", "用户名不能为空！");
        userNameLineEdit_->setFocus();
        return;
    }

    // --- TODO: 实现真正的注册逻辑 ---
    // 这里应该调用 VideoCallClient 的方法向 Janus 注册用户名
    // 例如: videoCallClient->registerUsername(userName);
    // 注册成功后，JanusClient (或其子类) 应该发出信号，
    // 在处理该信号的槽函数中执行下面的操作。

    // --- 当前为了测试，直接模拟注册成功 ---
    qInfo() << "模拟注册成功，用户名:" << userName;
    isRegistered_ = true;
    registerButton_->setEnabled(false); // 禁用注册按钮
    userNameLineEdit_->setEnabled(false); // 注册后用户名不可改
    callButton_->setEnabled(true);    // 启用呼叫按钮
    QMessageBox::information(this, "提示", "用户名注册成功 (模拟)");
}

void Widget::on_startSession_clicked()
{
    QString errorMsg;
    if (!validateInputs(errorMsg)) {
        QMessageBox::warning(this, "输入错误", errorMsg);
        return;
    }

    QUrl url(janusUrlLineEdit_->text().trimmed());

    // 禁用输入和按钮
    videoRoomRadioButton_->setEnabled(false);
    videoCallRadioButton_->setEnabled(false);
    janusUrlLineEdit_->setEnabled(false);
    cameraComboBox_->setEnabled(false);
    exitButton_->setEnabled(false);
    if (currentMode_ == UIMode::VideoRoom) {
        roomIdLineEdit_->setEnabled(false);
        joinRoomButton_->setEnabled(false);
    } else {
        userNameLineEdit_->setEnabled(false); // 注册时已禁用
        registerButton_->setEnabled(false);   // 注册时已禁用
        peerUserNameLineEdit_->setEnabled(false);
        callButton_->setEnabled(false);
    }

    qInfo() << "尝试连接 Janus 服务器并创建 Session:" << url.toString();
    janusClient_->connectToServer(url); // <<<=== 使用 JanusClient 连接
}

void Widget::on_exitButton_clicked()
{
    camera_->stopCapture();
    janusClient_->disconnectFromServer(); // <<<=== 使用 JanusClient 断开
    if (meetingUI_) {
        meetingUI_->close();
    }
    this->close();
}

// --- JanusClient 信号处理 ---

void Widget::onJanusStateChanged(JanusClient::State newState)
{
    qDebug() << "Widget: JanusClient state changed to:" << newState;
    // 可以根据状态更新 UI，例如显示状态文本
    // joinRoomButton_/callButton_ 的启用/禁用主要由 validate 和业务逻辑控制
    // exitButton_ 在连接过程中禁用，连接后或失败后启用
    if (newState == JanusClient::State::ConnectingWebSocket ||
        newState == JanusClient::State::CreatingSession) {
        exitButton_->setEnabled(false);
    } else {
        // 允许在任何其他状态下退出 (Disconnected, SessionActive, Error, Closing)
        exitButton_->setEnabled(true);
        // 如果状态是错误或断开，需要确保启动按钮也恢复可用
        if (newState == JanusClient::State::Disconnected || newState == JanusClient::State::Error) {
            onMeetingUiClosed(); // 调用清理逻辑恢复 UI
        }
    }
}

void Widget::onJanusSessionCreated(long long sessionId)
{
    qInfo() << "Widget: Janus session created successfully, ID:" << sessionId;

    // Session 建立成功后，启动摄像头并显示会议界面
    if (!meetingUI_) {

        QString roomId = (currentMode_ == UIMode::VideoRoom) ? roomIdLineEdit_->text().trimmed() : "P2P"; // RoomID 或 P2P 标识
        QString localUserName = (currentMode_ == UIMode::VideoCall) ? userNameLineEdit_->text().trimmed() : "Me"; // 用户名或默认值

        // --- TODO: 实际应用中，本地 UserID 可能来自 Janus 注册或其他服务 ---
        int localUserId = QRandomGenerator::global()->bounded(1000, 9999); // 暂时随机生成


        if (camera_->getSelectedCameraDescription().isEmpty()) {
            qWarning() << "Widget: Cannot create meeting UI: No camera selected.";
            onJanusErrorOccurred("未选择有效的摄像头设备。");
            janusClient_->disconnectFromServer(); // 没有摄像头，断开 Janus 连接
            return;
        }

        // --- 创建 VideoMeetingUI ---
        meetingUI_ = new VideoMeetingUI(roomId, localUserId, localUserName);

        // --- 连接 CCamera 到 VideoMeetingUI ---
        connect(camera_, &CCamera::frameReady, meetingUI_, &VideoMeetingUI::onLocalFrameReady, Qt::QueuedConnection);
        connect(meetingUI_, &VideoMeetingUI::closed, this, &Widget::onMeetingUiClosed);

        // --- 启动摄像头 ---
        if (camera_->startCapture()) {
            meetingUI_->show();
            this->hide(); // 隐藏登录窗口
        } else {
            QMessageBox::critical(this, "错误", "无法启动摄像头设备。");
            delete meetingUI_; // 清理
            meetingUI_ = nullptr;
            onJanusErrorOccurred("无法启动摄像头。"); // 触发错误处理
            janusClient_->disconnectFromServer(); // 无法启动摄像头，断开 Janus
            return;
        }
        // --- TODO: Session 创建成功后，子类 (VideoRoomClient/VideoCallClient) ---
        // --- 需要发送 'attach' 消息到相应的插件 ---
        // 例如: videoRoomClient->attachToPlugin();
        //       videoCallClient->attachToPlugin();
        // 并且可能需要发送 join (VideoRoom) 或发起呼叫 (VideoCall) 的消息

    } else {
        qWarning() << "Widget: Janus session created, but meeting UI already exists?";
    }

    exitButton_->setEnabled(true); // Session 建立后允许退出
}

void Widget::onJanusErrorOccurred(const QString &errorString)
{
    qWarning() << "Widget: JanusClient error:" << errorString;

    QString title = "Janus 错误";
    QWidget* parentWidget = this;
    if (meetingUI_ && meetingUI_->isVisible()) {
        parentWidget = meetingUI_; // 如果会议界面可见，在其上显示错误
        title = "连接错误";
    }

    QMessageBox::critical(parentWidget, title, "发生错误:\n" + errorString);

    // 错误发生后，通常需要恢复 UI 到可操作状态
    onMeetingUiClosed(); // 调用清理逻辑来恢复 Widget UI
}

// --- 其他槽函数 ---

void Widget::onMeetingUiClosed()
{
    qInfo() << "Widget: Meeting UI closed signal received.";
    camera_->stopCapture(); // 关闭摄像头
    janusClient_->disconnectFromServer(); // <<<=== 关闭 Janus 连接和 Session

    // 恢复 UI 控件状态
    videoRoomRadioButton_->setEnabled(true);
    videoCallRadioButton_->setEnabled(true);
    janusUrlLineEdit_->setEnabled(true);
    cameraComboBox_->setEnabled(true);
    exitButton_->setEnabled(true);

    // 恢复特定模式的控件
    roomIdLineEdit_->setEnabled(true);
    joinRoomButton_->setEnabled(true);
    // VideoCall 模式下，注册状态决定按钮状态
    userNameLineEdit_->setEnabled(!isRegistered_);
    registerButton_->setEnabled(!isRegistered_);
    peerUserNameLineEdit_->setEnabled(true);
    callButton_->setEnabled(isRegistered_);

    if (meetingUI_) {
        // 断开与 meetingUI_ 的连接
        disconnect(camera_, &CCamera::frameReady, meetingUI_, &VideoMeetingUI::onLocalFrameReady);
        disconnect(meetingUI_, &VideoMeetingUI::closed, this, &Widget::onMeetingUiClosed);
        // meetingUI_ 的其他连接也应在这里断开（如果 VideoMeetingUI 发出其他信号的话）

        meetingUI_->deleteLater(); // 安全删除
        meetingUI_ = nullptr;
    }

    // 可以在这里重置 VideoCall 的注册状态
    // isRegistered_ = false;
    // onModeChanged(); // 刷新按钮状态

    this->show(); // 显示登录窗口
}

void Widget::updateCameraComboBox(const QStringList &descriptions)
{
    cameraComboBox_->clear();
    bool hasCameras = !descriptions.isEmpty();

    if (hasCameras) {
        cameraComboBox_->addItems(descriptions);
    } else {
        cameraComboBox_->addItem("未找到摄像头设备");
    }
    cameraComboBox_->setEnabled(hasCameras);

    // 根据是否有摄像头以及当前模式，设置启动按钮的初始可用性
    bool canStart = hasCameras && !janusUrlLineEdit_->text().isEmpty(); // 简化判断
    joinRoomButton_->setEnabled(canStart);
    callButton_->setEnabled(canStart && isRegistered_); // VideoCall 需要先注册

}

void Widget::onCameraSelected(int index)
{
    if (!camera_->selectCamera(index)) {
        qWarning() << "选择摄像头失败，索引:" << index;
        onCameraError("选择摄像头失败。");
    }
}

void Widget::onCameraError(const QString &errorString)
{
    QMessageBox::warning(this, "摄像头错误", errorString);
    cameraComboBox_->setEnabled(false);
    // 禁用启动按钮
    joinRoomButton_->setEnabled(false);
    callButton_->setEnabled(false);
}

bool Widget::validateInputs(QString &errorMsg)
{
    errorMsg.clear();

    // 1. 验证 Janus URL
    if (janusUrlLineEdit_->text().trimmed().isEmpty()) {
        errorMsg = "Janus 服务器地址不能为空！";
        janusUrlLineEdit_->setFocus();
        return false;
    }
    QUrl url(janusUrlLineEdit_->text().trimmed());
    if (!url.isValid() || (url.scheme() != "ws" && url.scheme() != "wss")) {
        errorMsg = "Janus 服务器地址格式无效 (应为 ws://... 或 wss://...)！";
        janusUrlLineEdit_->setFocus();
        janusUrlLineEdit_->selectAll();
        return false;
    }

    // 2. 验证摄像头选择
    if (cameraComboBox_->currentIndex() < 0 || !cameraComboBox_->isEnabled() || cameraComboBox_->currentText().contains("未找到")) {
        errorMsg = "请选择有效的摄像头设备！";
        cameraComboBox_->setFocus();
        return false;
    }

    // 3. 根据当前模式验证特定输入
    if (currentMode_ == UIMode::VideoRoom) {
        if (roomIdLineEdit_->text().trimmed().isEmpty()) {
            errorMsg = "房间号不能为空！";
            roomIdLineEdit_->setFocus();
            return false;
        }
    } else { // VideoCall Mode
        if (!isRegistered_) {
            errorMsg = "请先注册用户名！";
            registerButton_->setFocus(); // 提示用户点击注册
            return false;
        }
        if (peerUserNameLineEdit_->text().trimmed().isEmpty()) {
            errorMsg = "对方用户名不能为空！";
            peerUserNameLineEdit_->setFocus();
            return false;
        }
        // 可以添加检查，不能呼叫自己
        if (userNameLineEdit_->text().trimmed() == peerUserNameLineEdit_->text().trimmed()) {
            errorMsg = "不能呼叫自己！";
            peerUserNameLineEdit_->setFocus();
            peerUserNameLineEdit_->selectAll();
            return false;
        }
    }

    return true;
}
